package com.gs.coursera.algorithms.core.graph;

import java.awt.BorderLayout;
import java.io.BufferedReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import javax.swing.JFrame;
import javax.swing.JScrollPane;

import com.gs.coursera.algorithms.core.graph.ui.GraphDisplayPanel;

/**
 * An abstract Graph.
 * 
 * @author Sabuj
 *
 * @param <T> Represents the content of each vertex
 */
public abstract class Graph<T, W extends Comparable<W>> {
	
	private int vertexCount;
	private List<Vertex<T, W>> vertices;
	private List<Edge<T, W>> edges;
	
	/**
	 * Create an empty graph with a fixed number of vertices.
	 * @param vertexCount
	 */
	public Graph(int vertexCount) {
		this.vertexCount = vertexCount;
		this.edges = new ArrayList<Edge<T,W>>();
		this.vertices = 
				new ArrayList<Vertex<T,W>>(vertexCount);
		for (int i = 0; i < vertexCount; i++) {
			vertices.add(null);
		}
	}

	public int getVertexCount() {
		return vertexCount;
	}

	public int getEdgeCount() {
		return edges.size();
	}

	public List<Vertex<T, W>> getVertices() {
		return vertices;
	}

	public List<Edge<T, W>> getEdges() {
		return edges;
	}

	public abstract List<Vertex<T, W>> getAdjacencyList(Vertex<T, W> v);
	public abstract boolean addVertex(Vertex<T, W> vertex);
	public abstract void addEdge(Edge<T, W> edge);
	public abstract void addEdge(T valueOne, T valueTwo, W weight);
	public abstract void addEdge(Vertex<T, W> startVertex, Vertex<T, W> endVertex, W weight);
    
	
	public void sortEdges(){
		Collections.sort(edges);
	}
	
	public void resetSearch(){
		for (Vertex<T, W> v : getVertices()) {
			v.setDiscovered(false);
		}
	}
	
    public void showAsAdjList(){
        JFrame frame = new JFrame("Graph");
        frame.setLocation(100, 100);
        frame.setSize(800, 640);
        frame.getContentPane().setLayout(new BorderLayout());
        GraphDisplayPanel gdp = new GraphDisplayPanel();
        gdp.display(this);
        frame.getContentPane().add(new JScrollPane(gdp), BorderLayout.CENTER );
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }

	public Vertex<T, W> getVertexByValue(T value) {
		for (Vertex<T, W> v : getVertices()) {
			if(v.getValue().equals(value))
				return v;
		}
		return null;
	}

	public Vertex<T,W> getVertexByNo(int vertexNo) {
		for (Vertex<T,W> v : vertices) {
			if(v.getVertexNumber() == vertexNo)
				return v;
		}
		return null;
	}
}
